import asyncio
import os
from google.adk.agents import Agent, LoopAgent, SequentialAgent
from google.adk.runners import InMemoryRunner
from google.adk.agents.invocation_context import InvocationContext
from google.adk.tools.tool_context import ToolContext
from google.adk.tools.mcp_tool.mcp_toolset import MCPToolset
from google.adk.tools.mcp_tool.mcp_session_manager import SseServerParams
from google.adk.models.lite_llm import LiteLlm
from dotenv import load_dotenv
from .server import search_POI
from .prompt import review, toolagent_prompt, information_report_prompt

load_dotenv()

# ========== 修复1: 为所有工具明确指定name属性 ==========
GAO_TOOL = MCPToolset(     
    connection_params=SseServerParams(url='https://mcp.api-inference.modelscope.net/06e5f888e0a64b/sse'),
)
"""
高德 MCP 服务接口说明
=======================

功能一：地理编码 maps_regeocode
将详细的结构化地址转换为经纬度坐标。

功能二：逆地理编码 maps_geo
将经纬度坐标转换为行政区划地址信息。

功能三：IP 定位 maps_ip_location
根据 IP 地址定位所在位置。

功能四：天气查询 maps_weather
根据城市名称或城市 adcode 查询天气信息。

功能五：骑行路径规划 maps_bicycling
规划骑行通勤方案，最大支持 500km。


功能六：步行路径规划 maps_direction_walking
规划 100km 内的步行通勤方案。

功能七：驾车路径规划 maps_direction_driving
规划小客车/轿车通勤方案。

功能八：公交路径规划 maps_direction_transit_integrated
综合火车、公交、地铁等公共交通方式的通勤方案。跨城场景需传起点和终点城市。
 
功能九：距离测量 maps_distance
测量两点经纬度之间的距离和时间。

功能十：关键词搜索 maps_text_search
根据关键词搜索 POI 信息。


功能十一：周边搜索 maps_around_search
根据关键词和中心点坐标搜索半径范围内的 POI 信息。

功能十二：详情搜索
根据 POI ID 获取详细地点信息。
"""



TRAVEL_TOOL = MCPToolset(   # 12306
    connection_params=SseServerParams(url='https://mcp12306-uuid1755267495.app-space.dplink.cc/sse'),
)
'''
12306 MCP 服务接口说明:

get-stations-code-in-city
通过城市名查询该城市所有车站的station_code，结果为列表。

get-station-code-of-city
通过城市名查询该城市对应的station_code，结果是唯一的。

get-station-code-by-name
通过车站名查询station_code，结果是唯一的。

get-station-by-telecode
通过station_telecode查询车站信息，结果是唯一的。

get-tickets
查询12306余票信息。

get-train-route-stations
查询列车途径车站信息。
'''
# SEARCH_TOOL = MCPToolset(   # 
#     connection_params=SseServerParams(url='https://papersearch2a9-uuid1755069417.app-space.dplink.cc/sse'),
# )
HUANGLI_TOOL = MCPToolset(   # 黄历
    connection_params=SseServerParams(url='https://4454c95ca2b2b298057cbcb3bdcbb566.app-space.dplink.cc/sse'),
)

os.environ["OPENAI_API_BASE"] = "https://api.siliconflow.cn/v1"
# model_name = 'openai/Pro/deepseek-ai/DeepSeek-R1'
model_name = 'deepseek/deepseek-chat'
# ========== 修复2: 创建代理实例而非类引用 ==========
IntentDetector = Agent(
    name="intent_detector",
    model=LiteLlm(model=model_name),
    instruction="""
你是指令解析专家，负责：
1. 识别用户意图分类（行程规划/车票查询/地图导航/闲聊）
2. 提取关键实体（出发地/目的地/日期等, 对于时间信息需要调用工具获取）
3. 提取额外附加信息用于增强模型效果（预算等）
4. 检测空闲状态（连续2轮无实质内容）
5. 每次用户提问后你需要输出下列JSON代码并和用户确认是否开始进行旅行规划
6. 如果用户同意开始进行旅行规划你需要设置下列JSON代码中`intent_confirmation`字段为true
7. 输出JSON格式：

{
  "intent": {
    "primary": "travel_planning | ticket_query | map_navigation | hotel_booking | attraction_info | weather_check | fare_comparison | other",
    "secondary": ["emergency_assist", "transit_transfer", "visa_info", null]
  },
  "entities": {
    "departure": {"value": "北京", "type": "city"},
    "arrival": {"value": "上海", "type": "city"},
    "date_range": {
      "start": "2025-08-20",
      "end": "2025-08-25",
      "flexibility": "±1天"
    },
    "time_window": ["08:00-10:00", "18:00-20:00"],
    "passengers": {
      "adults": 2,
      "children": 1,
      "infants": 0,
      "seniors": 1
    },
    "transport_modes": ["high_speed_rail", "airplane"],
    "seat_preference": "window",
    "luggage": {"backpacks": 2, "suitcases": 1}
  },
  "extra_information": {
    "budget": {
      "total": 5000,
      "currency": "CNY",
      "breakdown": {
        "transportation": 2000,
        "accommodation": 2000,
        "activities": 1000
      },
      ""
    },
    "accessibility_needs": ["wheelchair_ramp", "visual_guide"],
    "preferences": {
      "dietary": ["vegetarian", "no_dairy"],
      "hotel": ["swimming_pool", "gym"],
      "travel_style": "budget_backpacker"
    },
    "connectivity": "require_internet",
    "language_preferences": ["English", "Mandarin"],
    {...}
  },
  "context": {
    "conversation_progress": "initiating | refining | confirming",
    "last_intent": "ticket_query",
    "time_since_last_action": 120  // 单位：秒
  },
  "is_idle": false,
  "intent_confirmation": false
}""",
    description="用户意图检测和实体抽取",
    output_key="intent_analysis",
    tools=[GAO_TOOL, TRAVEL_TOOL, HUANGLI_TOOL],
)

ToolExecutor = Agent(
    name="tool_executor",
    model=LiteLlm(model=model_name),
    instruction=toolagent_prompt,
    description="智能路由到对应工具并执行",
    tools=[GAO_TOOL, TRAVEL_TOOL, HUANGLI_TOOL],
    output_key="tool_response"
)

InformationRefiner = Agent(
    name="info_refiner",
    model=LiteLlm(model=model_name),
    instruction="""
你是信息整理专家：
1. 输入：tool_response中的raw_response
2. 任务：
   - 过滤非核心字段
   - 数值单位标准化
   - 识别数据冲突点
3. 输出结构化知识图谱：

{
  "core_facts": [
    {"subject": "G123", "predicate": "duration", "object": "4.5小时"},
    {"subject": "G123", "predicate": "price", "object": "553元"}
  ],
  "anomalies": ["缺少票价信息"]
}
""",
    description="原始数据提炼和知识图谱构建",
    output_key="knowledge_graph"
)

ResponseComposer = Agent(
    name="response_composer",
    model=LiteLlm(model=model_name),
    instruction="""你是回复生成专家：
输入数据:
- intent_analysis
- knowledge_graph
- tool_response

任务:
1. 生成自然语言回复
2. 提供决策建议（如比较选项）
3. 空闲状态处理（is_idle=true且连续2轮则终止）
4. 输出最终结果：

{
  "response": "建议选择G123次列车...",
  "recommendations": {
    "best_option": "G123",
    "comparison": ["G123:4.5小时/553元", "G456:5小时/498元"]
  },
  "should_terminate": false
}
""",
    description="生成最终用户响应和决策建议",
    output_key="final_output"
)



QualityGate = Agent(
    name="quality_gate",
    model=LiteLlm(model=model_name),
    instruction=review,  # 请替换为实际的review提示词
    description="全流程输出质量验证",
    output_key="validation_report"
)

# ========== 修复3: 使用代理实例而非类引用 ==========
total_agents = [
    ToolExecutor, 
    InformationRefiner, 
    QualityGate,
    ResponseComposer, 
]

# ========== 修复4: 继承问题修正和状态处理 ==========
class RefinementLoop(LoopAgent):
    """迭代优化循环控制"""
    async def _run_async_impl(self, ctx: InvocationContext):
        # 明确检查状态值
        validation_report = ctx.session.state.get("validation_report", {})
        overall_pass = validation_report.get("overall_pass", False)
        print('进行循环')
        print('overall_pass=', overall_pass, 'validation_report=',validation_report)
        if overall_pass:
            print("质量验证通过，终止循环")
            return
        
        # 使用实例而非类
        for agent in total_agents:
            print(f"执行代理: {agent.name}")
            async for event in agent.run_async(ctx):
                yield event

# ========== 修复5: 确保所有子代理是有效的实例 ==========
refiner = RefinementLoop(
    name="refinement_loop",
    sub_agents=[QualityGate, ResponseComposer],  # 确保是已定义的代理实例
    max_iterations=2
)

InformationReport = Agent(
    name="information_report",
    model=LiteLlm(model=model_name),
    instruction=information_report_prompt,
    tools=[search_POI]
)

# ========== 修复6: 主工作流创建 ==========
branch_workflow = SequentialAgent(
    name='branch_workflow',
    sub_agents=[
        ToolExecutor,
        InformationRefiner,
        # ResponseComposer, 重复了下面有
        refiner,
        InformationReport,
    ]
)

import json

subsequentialAgent = SequentialAgent(
   name='main_workflow',
   sub_agents=[
      branch_workflow
   ]
)

intent_suggestion = Agent(
    name='intent_suggestion',
    model=LiteLlm(model=model_name),
    instruction="""# 🧭 意图建议专家

## 核心职责
您是在用户未确认旅行意图时提供指引的专家，负责：
1. 分析当前意图分析结果（intent_analysis）
2. 识别缺失的关键旅行信息
3. 生成友好的询问提示
4. 引导用户补充必要信息
5. 邀请用户确认开始旅行规划

## 输入数据来源
会话状态中的 intent_analysis 字段，数据结构如下：
{
  "intent": {...},
  "entities": {...},
  "extra_information": {...},
  "context": {...},
  "is_idle": false,
  "intent_confirmation": false
}

## 处理流程
1. **分析意图状态**:
   - 确定用户意图类型（travel_planning, ticket_query 等）
   - 检查实体字段的完整性（departure, arrival, date_range 等）

2. **识别缺失信息**:
   - 如缺少出发地：生成"您还未确定从哪里出发"
   - 如缺少目的地：生成"您还没告诉我目的地是哪里"
   - 如缺少日期：生成"您打算在什么时间出行"

3. **生成友好提示**:
   - 用自然语言组合缺失信息提示
   - 使用旅行管家的亲切口吻（"为了帮您更好地规划..."）
   - 添加1个与主题相关的emoji（✈️/🚄/🏨/🌍）

4. **邀请确认规划**:
   - 信息完整时："所有信息都已齐全，是否现在开始规划您的旅行？"
   - 信息缺失时："请提供上面的信息后，我们可以开始规划"

## 输出格式
直接生成自然语言回复文本（无需JSON格式）

## 示例场景
场景1：只缺少日期
输入: 有出发地北京、目的地上海
输出: "您想在哪几天从北京前往上海呢？📅"

场景2：完全未确定
输入: 所有实体字段为空
输出: "欢迎使用旅行管家！✈️ 您打算去哪旅行？什么时候出发？从哪里出发？"

场景3：信息完整但未确认
输入: 所有实体字段完整
输出: "所有信息都齐全啦！🎉 是否现在开始规划您的旅行？"
""",
    description="引导用户补充旅行信息并确认意图"
)

class IntentInsureLoop(LoopAgent):
    async def _run_async_impl(self, ctx: InvocationContext):
        # 明确检查状态值
        print(f"执行代理: {IntentDetector.name}")
        for ag in self.sub_agents:
          async for event in ag.run_async(ctx):
            yield event
        intent_analysis = ctx.session.state.get("intent_analysis", {})
        print(intent_analysis, type(intent_analysis))
        if type(intent_analysis) == type(str('a')):
           intent_analysis = intent_analysis.replace("```json","").replace("```","").strip()
           intent_analysis = json.loads(intent_analysis)
        print(intent_analysis, type(intent_analysis))
        intent_confirmation = intent_analysis.get("intent_confirmation", False)
        print('用户意图确认:', intent_confirmation)
        if intent_confirmation:
          print("用户意图验证通过，终止循环")
          print(f"执行代理: {subsequentialAgent.name}")
          async for event in subsequentialAgent.run_async(ctx):
            yield event
          return
        ctx.session.state['system_message'] = {
            "type": "clarification",
            "content": "您是否已经准备好开始旅行规划？"
        }
        async for event in intent_suggestion.run_async(ctx):
           yield event

intentInsureLoop = IntentInsureLoop(
    name='userIntentInsureLoop',
    sub_agents=[IntentDetector],
    max_iterations=4,
)

# ========== 修复7: 设置根代理 ==========
root_agent = intentInsureLoop